//
//  LOTScene.m
//  LottieAnimator
//
//  Created by Brandon Withrow on 12/14/15.
//  Copyright © 2015 Brandon Withrow. All rights reserved.
//

#import "LOTComposition.h"
#import "LOTLayer.h"
#import "LOTAssetGroup.h"
#import "LOTLayerGroup.h"
#import "LOTAnimationCache.h"

@implementation LOTComposition

# pragma mark - Convenience Initializers

+ (nullable instancetype)animationNamed:(nonnull NSString *)animationName {
    return [self animationNamed:animationName inBundle:[NSBundle mainBundle]];
}

+ (nullable instancetype)animationNamed:(nonnull NSString *)animationName inBundle:(nonnull NSBundle *)bundle {
    if (!animationName) {
        return nil;
    }
    animationName = [animationName stringByDeletingPathExtension];
    
    LOTComposition *comp = [[LOTAnimationCache sharedCache] animationForKey:animationName];
    if (comp) {
        return comp;
    }
    
    NSError *error;
    NSString *filePath = [bundle pathForResource:animationName ofType:@"json"];
    NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
    
    if (@available(iOS 9.0, *)) {
        if (!jsonData) {
            jsonData = [[NSDataAsset alloc] initWithName:animationName bundle:bundle].data;
        }
    }
    
    NSDictionary  *JSONObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData
                                                                           options:0 error:&error] : nil;
    if (JSONObject && !error) {
        LOTComposition *laScene = [[self alloc] initWithJSON:JSONObject withAssetBundle:bundle];
        [[LOTAnimationCache sharedCache] addAnimation:laScene forKey:animationName];
        laScene.cacheKey = animationName;
        return laScene;
    }
    NSLog(@"%s: Animation Not Found", __PRETTY_FUNCTION__);
    return nil;
}

+ (nullable instancetype)animationWithFilePath:(nonnull NSString *)filePath {
    NSString *animationName = filePath;
    
    LOTComposition *comp = [[LOTAnimationCache sharedCache] animationForKey:animationName];
    if (comp) {
        return comp;
    }
    
    NSError *error;
    NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
    NSDictionary  *JSONObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData
                                                                           options:0 error:&error] : nil;
    if (JSONObject && !error) {
        LOTComposition *laScene = [[self alloc] initWithJSON:JSONObject withAssetBundle:[NSBundle mainBundle]];
        laScene.rootDirectory = [filePath stringByDeletingLastPathComponent];
        [[LOTAnimationCache sharedCache] addAnimation:laScene forKey:animationName];
        laScene.cacheKey = animationName;
        return laScene;
    }
    
    NSLog(@"%s: Animation Not Found", __PRETTY_FUNCTION__);
    return nil;
}

+ (nonnull instancetype)animationFromJSON:(nonnull NSDictionary *)animationJSON {
    return [self animationFromJSON:animationJSON inBundle:[NSBundle mainBundle]];
}

+ (nonnull instancetype)animationFromJSON:(nullable NSDictionary *)animationJSON inBundle:(nullable NSBundle *)bundle {
    return [[self alloc] initWithJSON:animationJSON withAssetBundle:bundle];
}

#pragma mark - Initializer

- (instancetype _Nonnull)initWithJSON:(NSDictionary * _Nullable)jsonDictionary
                      withAssetBundle:(NSBundle * _Nullable)bundle {
    self = [super init];
    if (self) {
        if (jsonDictionary) {
            [self _mapFromJSON:jsonDictionary withAssetBundle:bundle];
        }
    }
    return self;
}

#pragma mark - Internal Methods

- (void)_mapFromJSON:(NSDictionary *)jsonDictionary
     withAssetBundle:(NSBundle *)bundle {
    NSNumber *width = jsonDictionary[@"w"];
    NSNumber *height = jsonDictionary[@"h"];
    if (width && height) {
        CGRect bounds = CGRectMake(0, 0, width.floatValue, height.floatValue);
        _compBounds = bounds;
    }
    
    _startFrame = [jsonDictionary[@"ip"] copy];
    _endFrame = [jsonDictionary[@"op"] copy];
    _framerate = [jsonDictionary[@"fr"] copy];
    
    if (_startFrame && _endFrame && _framerate) {
        NSInteger frameDuration = (_endFrame.integerValue - _startFrame.integerValue) - 1;
        NSTimeInterval timeDuration = frameDuration / _framerate.floatValue;
        _timeDuration = timeDuration;
    }
    
    NSArray *assetArray = jsonDictionary[@"assets"];
    if (assetArray.count) {
        _assetGroup = [[LOTAssetGroup alloc] initWithJSON:assetArray withAssetBundle:bundle withFramerate:_framerate];
    }
    
    NSArray *layersJSON = jsonDictionary[@"layers"];
    if (layersJSON) {
        _layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON
                                                withAssetGroup:_assetGroup
                                                 withFramerate:_framerate];
    }
    
    [_assetGroup finalizeInitializationWithFramerate:_framerate];
}

- (void)setRootDirectory:(NSString *)rootDirectory {
    _rootDirectory = rootDirectory;
    self.assetGroup.rootDirectory = rootDirectory;
}

@end
